package com.xcesys.extras.remoting.system.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.jws.WebService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.xcesys.extras.dataobject.system.CodeList;
import com.xcesys.extras.dataobject.system.CodeType;
import com.xcesys.extras.dataobject.system.Resource;
import com.xcesys.extras.dataobject.system.Role;
import com.xcesys.extras.dataobject.system.Setting;
import com.xcesys.extras.dataobject.system.User;
import com.xcesys.extras.model.TcCodeList;
import com.xcesys.extras.model.TcCodeType;
import com.xcesys.extras.model.TsResource;
import com.xcesys.extras.model.TsRole;
import com.xcesys.extras.model.TsSetting;
import com.xcesys.extras.model.TsUser;
import com.xcesys.extras.remoting.BaseRemotingServiceImpl;
import com.xcesys.extras.remoting.IDataObjectHelper;
import com.xcesys.extras.remoting.system.RSystemManagementService;
import com.xcesys.extras.system.service.TcCodeListService;
import com.xcesys.extras.system.service.TcCodeTypeService;
import com.xcesys.extras.system.service.TsResourceService;
import com.xcesys.extras.system.service.TsRoleService;
import com.xcesys.extras.system.service.TsSettingService;
import com.xcesys.extras.system.service.TsUserService;

@Service("RSystemManagementService")
@WebService(endpointInterface = "com.xcesys.extras.remoting.system.RSystemManagementService")
public class RSystemManagementServiceImpl extends BaseRemotingServiceImpl
		implements RSystemManagementService {

	@Autowired
	private TcCodeListService codeListService = null;

	@Autowired
	private TcCodeTypeService codeTypeService = null;

	@Autowired
	private TsSettingService paramService = null;

	@Autowired
	TsResourceService resourceService = null;

	@Autowired
	TsRoleService roleService = null;

	@Autowired
	TsUserService userService = null;

	@Autowired(required = false)
	@Qualifier("dozerDataObjectHelper")
	IDataObjectHelper dataHelper = null;

	@Override
	public void doAddResourcesToRole(Long roleId, Collection<Resource> resources) {
		// Collection<TsResource> tsResources = dataHelper.copyProperties(
		// TsResource.class, resources);
		// roleService.addResourcesToRole(roleId, tsResources);

	}

	@Override
	public void doAddRolesToUser(Long userId, List<Long> roles) {
		userService.addRolesToUser(userId, roles);
	}

	@Override
	public void doAddUsersToRole(Long roleId, List<Long> userIds) {
		roleService.addUsersToRole(roleId, userIds);
	}

	@Override
	public CodeList doCreateCodeList(CodeList codelist) {
		TcCodeList tcCodeList = dataHelper.copyProperties(TcCodeList.class,
				codelist);
		tcCodeList = codeListService.create(tcCodeList);
		return dataHelper.copyProperties(CodeList.class, tcCodeList);
	}

	@Override
	public CodeType doCreateCodeType(CodeType codeType) {
		TcCodeType tcCodeType = codeTypeService.create(dataHelper
				.copyProperties(TcCodeType.class, codeType));
		dataHelper.copyProperties(codeType, tcCodeType);
		return codeType;
	}

	@Override
	public Resource doCreateResource(Resource resource) {
		TsResource tmRes = dataHelper
				.copyProperties(TsResource.class, resource);
		tmRes = resourceService.create(tmRes);
		return dataHelper.copyProperties(Resource.class, tmRes);
	}

	@Override
	public Role doCreateRole(Role role) {
		TsRole tsRole = dataHelper.copyProperties(TsRole.class, role);
		// fill version fields for creating object.
		Role result = dataHelper.copyProperties(Role.class,
				roleService.create(tsRole));
		return result;
	}

	@Override
	public Setting doCreateSetting(Setting parameter) {
		TsSetting tsSetting = dataHelper.copyProperties(TsSetting.class,
				parameter);
		return dataHelper.copyProperties(Setting.class,
				paramService.create(tsSetting));
	}

	@Override
	public User doCreateUser(User user) {

		TsUser tmBasUser = dataHelper.copyProperties(TsUser.class, user);
		// fill version fields for creating object.
		User result = dataHelper.copyProperties(User.class,
				userService.create(tmBasUser));
		return result;

	}

	@Override
	public void doDeleteCodeList(CodeList codelist) {
		TcCodeList tcCodeList = dataHelper.copyProperties(TcCodeList.class,
				codelist);
		codeListService.delete(tcCodeList.getId());
	}

	@Override
	public void doDeleteCodeType(CodeType codeType) {
		TcCodeType tcCodeType = dataHelper.copyProperties(TcCodeType.class,
				codeType);
		codeTypeService.delete(tcCodeType.getId());
	}

	@Override
	public void doDeleteResource(Resource resource) {
		TsResource tmRes = dataHelper
				.copyProperties(TsResource.class, resource);
		resourceService.delete(tmRes);
	}

	@Override
	public void doDeleteRole(Role role) {
		roleService.delete(dataHelper.copyProperties(TsRole.class, role));

	}

	@Override
	public void doDeleteSetting(Setting parameter) {
		TsSetting tsSetting = dataHelper.copyProperties(TsSetting.class,
				parameter);
		paramService.delete(tsSetting);

	}

	@Override
	public void doDeleteUser(User user) {
		userService.delete(dataHelper.copyProperties(TsUser.class, user));
	}

	@Override
	public Collection<CodeList> doFindAllCodeLists() {
		Collection<CodeList> result = dataHelper.copyProperties(CodeList.class,
				codeListService.findAll());
		return result;

	}

	@Override
	public Collection<CodeType> doFindAllCodeTypes() {
		Collection<CodeType> result = dataHelper.copyProperties(CodeType.class,
				codeTypeService.findAll());
		// for (CodeType codeType : result) {
		// ArrayList<CodeList> codeLists = new ArrayList<CodeList>();
		// Collection<CodeList> tmpLists = dataHelper.copyProperties(
		// CodeList.class, codeType.getCodeLists());
		// if (tmpLists != null) {
		// codeLists.addAll(tmpLists);
		// }
		// codeType.setCodeLists(tmpLists);
		// }
		return result;
	}

	@Override
	public Collection<Resource> doFindAllResources() {
		Collection<TsResource> tmResources = resourceService.findAll();
		Collection<Resource> resources = dataHelper.copyProperties(
				Resource.class, tmResources);
		return resources;
	}

	@Override
	public Collection<Role> doFindAllRoles() {
		return dataHelper.copyProperties(Role.class, roleService.findAll());
	}

	@Override
	public Collection<Setting> doFindAllSettings() {
		return dataHelper.copyProperties(Setting.class, paramService.findAll());
	}

	@Override
	public Collection<User> doFindAllUsers() {
		return dataHelper.copyProperties(User.class, userService.findAll());
	}

	@Override
	public CodeList doFindCodeListById(Long id) {
		TcCodeList tcCodeList = codeListService.findById(id);
		CodeList result = dataHelper.copyProperties(CodeList.class, tcCodeList);
		return result;

	}

	@Override
	public Collection<CodeList> doFindCodeLists(String type) {
		Collection<CodeList> result = dataHelper.copyProperties(CodeList.class,
				codeListService.findByType(type));
		return result;

	}

	@Override
	public CodeType doFindCodeTypeById(Long id) {
		CodeType result = dataHelper.copyProperties(CodeType.class,
				codeTypeService.findById(id));
		return result;

	}

	@Override
	public Collection<CodeType> doFindCodeTypesByType(String type) {
		if (type != null && !"".equals(type)) {
			TcCodeType codeType = codeTypeService.findByName(type);
			ArrayList<CodeType> result = new ArrayList<CodeType>();
			result.add(dataHelper.copyProperties(CodeType.class, codeType));
			return result;
		} else {
			return dataHelper.copyProperties(CodeType.class,
					codeTypeService.findAll());
		}
	}

	@Override
	public Resource doFindResourceById(Long id) {
		return dataHelper.copyProperties(Resource.class,
				resourceService.findById(id));
	}

	@Override
	public Collection<Resource> doFindResourcesByParentId(Long parentResourceId) {
		Collection<TsResource> tmResources = resourceService
				.findByParentId(parentResourceId);
		Collection<Resource> resources = dataHelper.copyProperties(
				Resource.class, tmResources);
		return resources;
	}

	@Override
	public Collection<Resource> doFindResourcesByParentIdAndType(
			Long parentResourceId, String resourceType) {
		Collection<TsResource> tmResources = resourceService
				.findByParentIdAndType(parentResourceId, resourceType);
		Collection<Resource> resources = dataHelper.copyProperties(
				Resource.class, tmResources);
		return resources;
	}

	@Override
	public Collection<Resource> doFindResourcesByParentIdAndTypes(
			Long parentResourceId, String[] resourceTypes) {
		Collection<TsResource> tmResources = resourceService
				.findByParentIdAndTypes(parentResourceId, resourceTypes);
		Collection<Resource> resources = dataHelper.copyProperties(
				Resource.class, tmResources);
		return resources;
	}

	@Override
	public Collection<Resource> doFindResourcesByRoleId(Long roleId) {
		TsRole TsRole = roleService.findById(roleId);
		if (TsRole == null)
			return null;
		// Set<TsResource> tsResources = TsRole.getTsResources();
		ArrayList<TsResource> result = new ArrayList<TsResource>();
		// result.addAll(tsResources);
		return dataHelper.copyProperties(Resource.class, result);
	}

	@Override
	public Collection<Resource> doFindResourcesByType(String resourceType) {
		Collection<TsResource> tmResources = resourceService
				.findByType(resourceType);
		Collection<Resource> resources = dataHelper.copyProperties(
				Resource.class, tmResources);
		return resources;
	}

	@Override
	public Collection<Resource> doFindResourcesInRoleNames(String[] roleNames) {
		if (roleNames == null || roleNames.length <= 0)
			return null;
		ArrayList<TsResource> tsResources = new ArrayList<TsResource>();
		for (int i = 0; i < roleNames.length; i++) {
			TsRole role = roleService.findByName(roleNames[i]);
			if (role != null) {
				// tsResources.addAll(role.getTsResources());
			}
		}

		return dataHelper.copyProperties(Resource.class, tsResources);
	}

	@Override
	public Collection<Role> doFindRolesByCondition(String nameEn,
			String nameZh, String description) {
		return dataHelper.copyProperties(Role.class,
				roleService.findByCondition(nameEn, description));
	}

	@Override
	public Role doFindRolesByRoleId(Long roleId) {
		return dataHelper.copyProperties(Role.class,
				roleService.findById(roleId));
	}

	@Override
	public Collection<Role> doFindRolesByUserId(Long userId) {
		TsUser tsUser = userService.findById(userId);
		if (tsUser == null)
			return null;
		Set<TsRole> tsRoles = tsUser.getTsRoles();
		ArrayList<TsRole> result = new ArrayList<TsRole>();
		result.addAll(tsRoles);
		return dataHelper.copyProperties(Role.class, result);
	}

	@Override
	public Collection<Role> doFindRolesByUsername(String username) {
		TsUser tsUser = userService.findByUsername(username);
		if (tsUser == null)
			return null;
		Set<TsRole> tsRoles = tsUser.getTsRoles();
		ArrayList<TsRole> result = new ArrayList<TsRole>();
		result.addAll(tsRoles);
		return dataHelper.copyProperties(Role.class, result);
	}

	@Override
	public Setting doFindSettingById(Long id) {
		return dataHelper.copyProperties(Setting.class,
				paramService.findById(id));
	}

	@Override
	public User doFindUserById(Long id) {
		return dataHelper.copyProperties(User.class, userService.findById(id));
	}

	@Override
	public User doFindUserByUsername(String username) {
		return dataHelper.copyProperties(User.class,
				userService.findByUsername(username));
	}

	@Override
	public Collection<User> doFindUsersByRoleId(Long roleId) {
		TsRole tsRole = roleService.findById(roleId);
		if (tsRole == null)
			return null;
		Set<TsUser> tsUsers = tsRole.getTsUsers();
		ArrayList<TsUser> result = new ArrayList<TsUser>();
		result.addAll(tsUsers);
		return dataHelper.copyProperties(User.class, result);
	}

	@Override
	public Collection<User> doFindUsersByRoleName(String rolename) {
		TsRole tsRole = roleService.findByName(rolename);
		if (tsRole == null)
			return null;
		Set<TsUser> tsUsers = tsRole.getTsUsers();
		ArrayList<TsUser> result = new ArrayList<TsUser>();
		result.addAll(tsUsers);
		return dataHelper.copyProperties(User.class, result);
	}

	@Override
	public void doRemoveResourcesFromRole(Long roleId,
			Collection<Resource> resources) {
		// Collection<TsResource> tsResources = dataHelper.copyProperties(
		// TsResource.class, resources);
		// roleService.removeResourcesFromRole(roleId, tsResources);
	}

	@Override
	public void doRemoveRolesFromUser(Long userId, Collection<Role> roles) {
		List<Long> roleIds = new ArrayList<Long>();
		for (Role r : roles) {
			roleIds.add(r.getId());
			;
		}
		userService.removeRolesFromUser(userId, roleIds);
	}

	@Override
	public void doRemoveUsersFromRole(Long roleId, List<Long> userIds) {
		roleService.removeUsersFromRole(roleId, userIds);

	}

	@Override
	public CodeList doUpdateCodeList(CodeList codelist) {
		// TcCodeList tcCodeList = codeListService.doFindById(codelist.getId());
		TcCodeList tcCodeList = dataHelper.copyProperties(TcCodeList.class,
				codelist);
		codeListService.update(tcCodeList);
		return codelist;
	}

	@Override
	public CodeType doUpdateCodeType(CodeType codeType) {
		TcCodeType tcCodeType = dataHelper.copyProperties(TcCodeType.class,
				codeType);
		codeTypeService.update(tcCodeType);
		dataHelper.copyProperties(codeType, tcCodeType);
		return codeType;
	}

	@Override
	public Resource doUpdateResource(Resource resource) {
		TsResource tsResource = resourceService.findById(resource.getId());
		dataHelper.copyProperties(tsResource, resource);
		resourceService.update(tsResource);
		dataHelper.copyProperties(resource, tsResource);
		return resource;
	}

	@Override
	public Role doUpdateRole(Role role) {
		if (role == null) {
			return role;
		}
		// find existed first
		TsRole tsRole = roleService.findById(role.getId());
		// TsRole tsRole = dataHelper.copyProperties(TsRole.class, role);
		dataHelper.copyProperties(tsRole, role);
		// fill version fields for creating object.
		roleService.update(tsRole);
		dataHelper.copyProperties(role, tsRole);
		return role;
	}

	@Override
	public Setting doUpdateSetting(Setting setting) {
		TsSetting tsSetting = dataHelper.copyProperties(TsSetting.class,
				setting);
		paramService.update(tsSetting);
		dataHelper.copyProperties(setting, tsSetting);
		return setting;
	}

	@Override
	public User doUpdateUser(User user) {
		// find saved object first
		TsUser toBeUpdated = userService.findById(user.getId());
		// copy properties value from input object ot saved object.
		dataHelper.copyProperties(toBeUpdated, user);
		// fill version fields for creating object.
		userService.update(toBeUpdated);
		dataHelper.copyProperties(user, toBeUpdated);
		return user;
	}

}
